bitkeeper revision 1.826 (4061dc112UgMgszCetN8gJQ20L0AUw)
authormwilli2@equilibrium.research.intel-research.net <mwilli2@equilibrium.research.intel-research.net>
Wed, 24 Mar 2004 19:05:53 +0000 (19:05 +0000)
committermwilli2@equilibrium.research.intel-research.net <mwilli2@equilibrium.research.intel-research.net>
Wed, 24 Mar 2004 19:05:53 +0000 (19:05 +0000)
Features to pause domains (and repin them) synchronously.

tools/examples/xc_dom_control.py
xen/common/dom0_ops.c
xen/common/sched_bvt.c
xen/common/sched_rrobin.c
xen/common/schedule.c
xen/include/xen/sched-if.h
xen/include/xen/sched.h

index 0ca2c97ac2244caef50c9fcea37e9420d7c32972..c21ff3c880a990781e68186f10acc76c8371a6de 100755 (executable)
@@ -85,17 +85,9 @@ elif cmd == 'pincpu':
         sys.exit(-1)
 
     cpu = int(sys.argv[3])
-    orig_state = xc.domain_getinfo(first_dom=dom, max_doms=1)[0]['stopped']
-
-    while xc.domain_getinfo(first_dom=dom, max_doms=1)[0]['stopped'] != 1:
-       xc.domain_stop( dom=dom )
-       time.sleep(0.1)
-
+    
     rc = xc.domain_pincpu( dom, cpu )
 
-    if orig_state == 0:
-       xc.domain_start( dom=dom )
-
 elif cmd == 'list':
     print 'Dom  Name             Mem(kb)  CPU  State  Time(s)'
     for domain in xc.domain_getinfo():
index a5f7041f0b402a84934cfaf295faa7923caa5ded..7b75688cb68cffe851034b4cde27980ce50dc15f 100644 (file)
@@ -160,40 +160,48 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
 
     case DOM0_PINCPUDOMAIN:
     {
-        struct task_struct * p = find_domain_by_id(op->u.pincpudomain.domain);
-       int cpu = op->u.pincpudomain.cpu;
-        ret = -EINVAL;
-        if ( p != NULL )
+        domid_t dom = op->u.pincpudomain.domain;
+        
+        if ( dom == current->domain || dom == IDLE_DOMAIN_ID )
+            ret = -EINVAL;
+        else
         {
-           if ( cpu == -1 )
-            {
-                p->cpupinned = 0;
-                ret = 0;
-           }
-            else
+            struct task_struct * p = find_domain_by_id(dom);
+            int cpu = op->u.pincpudomain.cpu;
+            int we_paused = 0;
+            
+            ret = -ESRCH;
+            
+            if ( p != NULL )
             {
-               /* For the moment, we are unable to move running
-                   domains between CPUs. (We need a way of synchronously
-                   stopping running domains). For now, if we discover the
-                   domain is not stopped already then cowardly bail out
-                   with ENOSYS */
-
-               if( !(p->state & TASK_STOPPED) ) 
+                if ( cpu == -1 )
                 {
-                    ret = -ENOSYS;
-               }
+                    p->cpupinned = 0;
+                    ret = 0;
+                }
                 else
                 {
-                   /* We need a task structure lock here!!! 
-                      FIX ME!! */
-                   cpu = cpu % smp_num_cpus;
-                   p->processor = cpu;
-                   p->cpupinned = 1;
+                    /* Pause domain if necessary. */
+                    if( !(p->state & TASK_STOPPED) && !(p->state & TASK_PAUSED) )
+                    {
+                        sched_pause_sync(p);
+                        we_paused = 1;
+                    }
+                    
+                    /* We need a task structure lock here!!! 
+                       FIX ME!! */
+                    cpu = cpu % smp_num_cpus;
+                    p->processor = cpu;
+                    p->cpupinned = 1;
+                    
+                    if ( we_paused )
+                        wake_up(p);
+                    
                     ret = 0;
                 }
-            }
-            put_task_struct(p);
-        }      
+                put_task_struct(p);
+            }          
+        }
     }
     break;
 
index 3052d1e98c20238ad5b5d9b71725ca387de0b314..9db7d2ce16d0eaeae152720615f27e1aaafc667b 100644 (file)
@@ -401,6 +401,11 @@ int bvt_init_scheduler()
     return 0;
 }
 
+static void bvt_pause(struct task_struct *p)
+{
+    if( __task_on_runqueue(p) )
+        __del_from_runqueue(p);
+}
 
 struct scheduler sched_bvt_def = {
     .name     = "Borrowed Virtual Time",
@@ -419,5 +424,6 @@ struct scheduler sched_bvt_def = {
     .dump_settings  = bvt_dump_settings,
     .dump_cpu_state = bvt_dump_cpu_state,
     .dump_runq_el   = bvt_dump_runq_el,
+    .pause          = bvt_pause,
 };
 
index 544803f1faa3a020ec84303d7a452123f4e387db..90cbfc7c29247e1346773221a67840aa9259ae51 100644 (file)
@@ -42,6 +42,12 @@ static void rr_dump_settings()
     printk("rr_slice = %llu ", rr_slice);
 }
 
+static void rr_pause(struct task_struct *p)
+{
+    if ( __task_on_runqueue(p) )
+        __del_from_runqueue(p);
+}
+
 struct scheduler sched_rrobin_def = {
     .name     = "Round-Robin Scheduler",
     .opt_name = "rrobin",
@@ -51,6 +57,7 @@ struct scheduler sched_rrobin_def = {
     .do_schedule    = rr_do_schedule,
     .control        = rr_ctl,
     .dump_settings  = rr_dump_settings,
+    .pause          = rr_pause,
 };
 
 
index 0738a843db8010f0ce5c97a2bd2ca01e0ad39d84..a43ca56be28268105daab64cc5687ce2b8d5e0cc 100644 (file)
@@ -167,7 +167,6 @@ int sched_rem_domain(struct task_struct *p)
     return 1;
 }
 
-
 void init_idle_task(void)
 {
     unsigned long flags;
@@ -281,6 +280,35 @@ long do_sched_op(unsigned long op)
     return ret;
 }
 
+
+/* sched_pause_sync - synchronously pause a domain's execution */
+void sched_pause_sync(struct task_struct *p)
+{
+    unsigned long flags;
+    int cpu = p->processor;
+
+    spin_lock_irqsave(&schedule_lock[cpu], flags);
+
+    if ( schedule_data[cpu].curr != p )
+        /* if not the current task, we can remove it from scheduling now */
+        SCHED_FN(pause, p);
+
+    p->state = TASK_PAUSED;
+    
+    spin_unlock_irqrestore(&schedule_lock[cpu], flags);
+
+    /* spin until domain is descheduled by its local scheduler */
+    while ( schedule_data[cpu].curr == p )
+    {
+            set_bit(_HYP_EVENT_NEED_RESCHED, &p->hyp_events);
+            hyp_event_notify(1 << cpu);
+            do_yield();
+    }
+    
+    
+    /* The domain will not be scheduled again until we do a wake_up(). */
+}
+
 /* Per-domain one-shot-timer hypercall. */
 long do_set_timer_op(unsigned long timeout_hi, unsigned long timeout_lo)
 {
index 683e73d4f66c6aa00cd42c5d9526864463a2edbc..cf7358719a90c97c2d0bf73d3614976ff1ce9846 100644 (file)
@@ -50,6 +50,7 @@ struct scheduler
     void         (*dump_settings)  (void);
     void         (*dump_cpu_state) (int);
     void         (*dump_runq_el)   (struct task_struct *);
+    void         (*pause)          (struct task_struct *);
 };
 
 /* per CPU scheduler information */
index c41123ebc46036c507e5f39539f8a51420772cae..c23ffa30ae8854d866a70020c97fd4d745db2569 100644 (file)
@@ -163,6 +163,7 @@ struct task_struct
  *                       arbitrary event or timer.
  * TASK_STOPPED:         Domain is stopped.
  * TASK_DYING:           Domain is about to cross over to the land of the dead.
+ * TASK_PAUSED:          Task currently removed from scheduling.
  */
 
 #define TASK_RUNNING             0
@@ -170,7 +171,7 @@ struct task_struct
 #define TASK_UNINTERRUPTIBLE     2
 #define TASK_STOPPED             4
 #define TASK_DYING               8
-#define TASK_SCHED_PRIV          16
+#define TASK_PAUSED             16
 
 #include <asm/uaccess.h> /* for KERNEL_DS */
 
@@ -246,6 +247,7 @@ void sched_add_domain(struct task_struct *p);
 int  sched_rem_domain(struct task_struct *p);
 long sched_ctl(struct sched_ctl_cmd *);
 long sched_adjdom(struct sched_adjdom_cmd *);
+void sched_pause_sync(struct task_struct *);
 void init_idle_task(void);
 void __wake_up(struct task_struct *p);
 void wake_up(struct task_struct *p);